﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace PInfoModel
{
	internal static class DgmlExtensions
	{
		public const string NamespaceUri = "http://schemas.microsoft.com/vs/2009/dgml";

		const string PROPERTY_TYPES = "\t<Property Id=\"Type\" Description=\"The set of types associated with this region.\" DataType=\"System.String\" />\n";

		const string PROPERTY_USEMOD = "\t<Property Id=\"UseMod\" Description=\"The use/mod sites for the objects represented by this node.\" DataType=\"System.String\" />\n";

		const string PROPERTY_USEEXT = "\t<Property Id=\"ExternalUse\" Description=\"Boolean flag if the node may represent used external scope objects.\" DataType=\"System.String\" />\n";
		const string PROPERTY_VMODEXT = "\t<Property Id=\"ExternalModValue\" Description=\"Boolean flag if the node may represent value modified external scope objects.\" DataType=\"System.String\" />\n";
		const string PROPERTY_SMODEXT = "\t<Property Id=\"ExternalModStruct\" Description=\"Boolean flag if the node may represent structural modified external scope objects.\" DataType=\"System.String\" />\n";

		const string PROPERTY_USEINT = "\t<Property Id=\"InternalUse\" Description=\"Boolean flag if the node may represent used internally allocated objects.\" DataType=\"System.String\" />\n";
		const string PROPERTY_VMODINT = "\t<Property Id=\"InternalModValue\" Description=\"Boolean flag if the node may represent value modified internally allocated objects.\" DataType=\"System.String\" />\n";
		const string PROPERTY_SMODINT = "\t<Property Id=\"InternalModStruct\" Description=\"Boolean flag if the node may represent structural modified internally allocated objects.\" DataType=\"System.String\" />\n";

		const string PROPERTY_ESCAPE = "\t<Property Id=\"Escape\" Description=\"The escape lines for internally allocated objects.\" DataType=\"System.String\" />\n";
		const string PROPERTY_INTERNALORIG = "\t<Property Id=\"InternalOrig\" Description=\"Boolean flag if the node may represent objects escaping into (allocated in) the callee scope.\" DataType=\"System.String\" />\n";

		const string PROPERTY_EXTIDENTITY = "\t<Property Id=\"Identities\" Description=\"Set of external identities.\" DataType=\"System.String\" />\n";
		const string PROPERTY_EXTERNALORIG = "\t<Property Id=\"ExternalOrig\" Description=\"Boolean flag if the node may represent objects from the caller scope.\" DataType=\"System.String\" />\n";

		const string PROPERTY_TARGETOFFSETS = "\t<Property Id=\"TargetOffsets\" Description=\"String of target offsets for the pointer/reference.\" DataType=\"System.String\" />\n";
		const string PROPERTY_MAYALIAS = "\t<Property Id=\"MayAliasWMulti\" Description=\"Boolean flag if edge represents possibly aliasing pointers.\" DataType=\"System.String\" />\n";
		const string PROPERTY_PUREINJ = "\t<Property Id=\"PureInjective\" Description=\"Boolean flag if edge only internal edges that are injective (work around multi edge in DGML).\" DataType=\"System.String\" />\n";
		const string PROPERTY_MAYNULL = "\t<Property Id=\"MayNull\" Description=\"Boolean flag if edge represents possibly null pointers.\" DataType=\"System.String\" />\n";

		const string PROPERTY_TRAVERSEINFO = "\t<Property Id=\"TraverseInfo\" Description=\"Any traversal info associated with the edge.\" DataType=\"System.String\" />\n";
		
		const string FlatStyle = "\t<Style TargetType=\"Node\"><Setter Property=\"Style\" Value=\"Plain\" /><Setter Property=\"NodeRadius\" Value=\"2\" /></Style>\n";

		const string CONDITION_SHOW_MAYALIAS = "\t<Style TargetType=\"Link\" IsEnabled=\"true\" GroupLabel=\"MayAliasWMulti\" ValueLabel=\"1\">\n\t\t<Condition Expression=\"MayAliasWMulti\" />\n\t\t<Setter Property=\"Stroke\" Value=\"Orange\" />\n\t\t<Setter Property=\"Background\" Value=\"Orange\" />\n\t</Style>";
		const string CONDITION_SHOW_MAYNULL = "\t<Style TargetType=\"Link\" IsEnabled=\"true\" GroupLabel=\"MayNull\" ValueLabel=\"1\">\n\t\t<Condition Expression=\"MayNull\" />\n\t\t<Setter Property=\"StrokeDashArray\" Value=\"5\" />\n\t</Style>";

		const string CONDITION_SHOWUSEMOD1 = "\t<Style TargetType=\"Node\" IsEnabled=\"false\" GroupLabel=\"UseMod\" ValueLabel=\"1\">\n\t\t<Condition Expression=\"Use\" />\n\t\t<Setter Property=\"Background\" Value=\"Green\" />\n\t</Style>";
		const string CONDITION_SHOWUSEMOD2 = "\t<Style TargetType=\"Node\" IsEnabled=\"false\" GroupLabel=\"UseMod\" ValueLabel=\"2\">\n\t\t<Condition Expression=\"ModValue\" />\n\t\t<Setter Property=\"Background\" Value=\"Purple\" />\n\t</Style>";
		const string CONDITION_SHOWUSEMOD3 = "\t<Style TargetType=\"Node\" IsEnabled=\"false\" GroupLabel=\"UseMod\" ValueLabel=\"3\">\n\t\t<Condition Expression=\"ModStruct\" />\n\t\t<Setter Property=\"Background\" Value=\"Red\" />\n\t</Style>";

		const string CONDITION_SHOW_INTEXT1 = "\t<Style TargetType=\"Node\" IsEnabled=\"false\" GroupLabel=\"Source\" ValueLabel=\"1\">\n\t\t<Condition Expression=\"ExternalOrig\" />\n\t\t<Setter Property=\"Background\" Value=\"Orange\" />\n\t</Style>";
		const string CONDITION_SHOW_INTEXT2 = "\t<Style TargetType=\"Node\" IsEnabled=\"false\" GroupLabel=\"Source\" ValueLabel=\"2\">\n\t\t<Condition Expression=\"InternalOrig\" />\n\t\t<Setter Property=\"Background\" Value=\"Blue\" />\n\t</Style>";
		const string CONDITION_SHOW_INTEXT3 = "\t<Style TargetType=\"Node\" IsEnabled=\"false\" GroupLabel=\"Source\" ValueLabel=\"3\">\n\t\t<Condition Expression=\"ExternalOrig and InternalOrig\" />\n\t\t<Setter Property=\"Background\" Value=\"Purple\" />\n\t</Style>";
		
		internal static void WriteCategoriesAndProperties(XmlWriter xw)
		{
			xw.WriteStartElement("Properties");
			xw.WriteRaw(PROPERTY_TYPES);

			xw.WriteRaw(PROPERTY_USEMOD);
			xw.WriteRaw(PROPERTY_USEEXT);
			xw.WriteRaw(PROPERTY_VMODEXT);
			xw.WriteRaw(PROPERTY_SMODEXT);
			xw.WriteRaw(PROPERTY_USEINT);
			xw.WriteRaw(PROPERTY_VMODINT);
			xw.WriteRaw(PROPERTY_VMODEXT);

			xw.WriteRaw(PROPERTY_ESCAPE);
			xw.WriteRaw(PROPERTY_INTERNALORIG);

			xw.WriteRaw(PROPERTY_EXTIDENTITY);
			xw.WriteRaw(PROPERTY_EXTERNALORIG);

			xw.WriteRaw(PROPERTY_TARGETOFFSETS);
			xw.WriteRaw(PROPERTY_MAYALIAS);
			xw.WriteRaw(PROPERTY_PUREINJ);
			xw.WriteRaw(PROPERTY_MAYNULL);

			xw.WriteRaw(PROPERTY_TRAVERSEINFO);

			xw.WriteEndElement();
		}

		internal static void WriteStyles(XmlWriter xw)
		{
			xw.WriteStartElement("Styles");
			xw.WriteRaw(FlatStyle);
			
			xw.WriteRaw(CONDITION_SHOWUSEMOD3);
			xw.WriteRaw(CONDITION_SHOWUSEMOD2);
			xw.WriteRaw(CONDITION_SHOWUSEMOD1);

			xw.WriteRaw(CONDITION_SHOW_INTEXT3);
			xw.WriteRaw(CONDITION_SHOW_INTEXT2);
			xw.WriteRaw(CONDITION_SHOW_INTEXT1);

			xw.WriteRaw(CONDITION_SHOW_MAYALIAS);
			xw.WriteRaw(CONDITION_SHOW_MAYNULL);

			xw.WriteEndElement();
		}
	}
}
